using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SkinableFormsLib
{
	public class LWProgressBarCustom : LWProgressBar
	{

		internal SolidBrush _foreBrush = new SolidBrush(Color.Black);
		internal SolidBrush _backBrush = new SolidBrush(Color.Black);
		

		internal SolidBrush _lwBorderBrush = (SolidBrush)Brushes.Black;
		private Color _lwBorderColor = Color.Black;
		public Color LWBorderColor
		{
			get
			{
				return _lwBorderColor;
			}
			set
			{
				_lwBorderColor = value;
				_lwBorderBrush = new SolidBrush(value);
			}
		}

		private int _lwBorderWidth = 0;
		public int LWBorderWidth
		{
			get
			{
				return _lwBorderWidth;
			}
			set
			{
				_lwBorderWidth = value;
			}
		}

		private int _lwBorderRadius = 0;
		public int LWBorderRadius
		{
			get
			{
				return _lwBorderRadius;
			}
			set
			{
				_lwBorderRadius = value;
			}
		}




		internal Graphics _lwGraphics;
		public LWProgressBarCustom()
			: base()
		{
			_backBrush = new SolidBrush(BackColor);
			_foreBrush = new SolidBrush(ForeColor);
		}

		protected override void OnResize(System.EventArgs e)
		{

			if (_lwBitmap == null || _lwBitmap.Width != Width || _lwBitmap.Height != Height)
			{

				if (Width != 0 && Height != 0)
				{
					this.DisposeInternal();
					/*_lwBitmap = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
					_lwGraphics = Graphics.FromImage(_lwBitmap);
					_lwRectangle = new Rectangle(0, 0, _lwBitmap.Width, _lwBitmap.Height);*/
					CreateBitmap();
				}
			}
		}
		private void CreateBitmap()
		{
			if (Width != 0 && Height != 0)
			{
				_lwBitmap = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
				_lwGraphics = Graphics.FromImage(_lwBitmap);
				_lwGraphics.SmoothingMode = SmoothingMode.HighQuality;
				_lwGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
				_lwGraphics.CompositingQuality = CompositingQuality.HighQuality;
				_lwRectangle = new Rectangle(0, 0, _lwBitmap.Width, _lwBitmap.Height);
				CreateBorder();
			}
		}


		internal override void DisposeInternal()
		{
			base.DisposeInternal();
			if (_lwGraphics != null)
				_lwGraphics.Dispose();

		}


		private Utils.ProgressBarOrientation _lwOrientation = Utils.ProgressBarOrientation.Horizontal;
		public Utils.ProgressBarOrientation LWOrientation
		{
			get
			{
				return _lwOrientation;
			}
			set
			{
				_lwOrientation = value;
			}
		}






		public override Color BackColor
		{
			get
			{
				return base.BackColor;
			}
			set
			{
				base.BackColor = value;
				_backBrush = new SolidBrush(value);
			}
		}

		public override Color ForeColor
		{
			get
			{
				return base.ForeColor;
			}
			set
			{
				base.ForeColor = value;
				_foreBrush = new SolidBrush(value);
			}
		}


		private int chunkSizeHorizontal = 5;
		private int chunkSizeVertical = 5;

		private int chunkSpaceHorizontal = 1;
		private int chunkSpaceVertical = 1;


		private int _lwChunkSize = 5;
		public int LWChunkSize
		{
			get
			{
				return _lwChunkSize;
			}
			set
			{
				_lwChunkSize = value;
				chunkSizeHorizontal = value;
				chunkSizeVertical = value;

			}
		}
		private int _lwChunkSpacing = 1;
		public int LWChunkSpacing
		{
			get
			{
				return _lwChunkSpacing;
			}
			set
			{
				_lwChunkSpacing = value;
				chunkSpaceHorizontal = value;
				chunkSpaceVertical = value;
			}
		}



		internal void DrawHorizontal(Graphics g)
		{
			if (!this.LWTransparent)
			{
				g.FillRectangle(_backBrush, _lwRectangle);
			}
			int p = (int)(100 * Value / Maximum);



			if (this.Style == ProgressBarStyle.Blocks)
			{
				int mc = Size.Width / (chunkSizeHorizontal + chunkSpaceHorizontal);
				int ac = (p * mc) / 100;
				for (int i = 0; i < ac; i++)
				{
					Rectangle r = new Rectangle();
					r.X = i * (chunkSizeHorizontal + chunkSpaceHorizontal);
					if (this.RightToLeftLayout)
						r.X = Width - r.X;
					r.Y = 0;
					r.Height = Height;
					r.Width = chunkSizeHorizontal;
					g.FillRectangle(_foreBrush, r);
				}
			}
			else
			{
				Rectangle r = new Rectangle();
				r.X = 0;

				r.Y = 0;
				r.Height = Height;
				r.Width = p * Width / 100;

				if (this.RightToLeftLayout)
					r.X = Width - r.Width;

				g.FillRectangle(_foreBrush, r);
			}

		}
		internal void DrawVertical(Graphics g)
		{
			if (!this.LWTransparent)
			{
				g.FillRectangle(_backBrush, _lwRectangle);
			}
			int p = (int)(100 * Value / Maximum);
			if (this.Style == ProgressBarStyle.Blocks)
			{
				int mc = Size.Height / (chunkSizeVertical + chunkSpaceVertical);
				int ac = (p * mc) / 100;
				for (int i = 0; i < ac; i++)
				{
					Rectangle r = new Rectangle();
					r.Y = Height - i * (chunkSizeVertical + chunkSpaceVertical);
					r.X = 0;
					r.Height = chunkSizeVertical;
					r.Width = Width;
					g.FillRectangle(_foreBrush, r);
				}
			}
			else
			{
				Rectangle r = new Rectangle();
				r.X = 0;
				r.Y = Height - p * Height / 100;
				r.Height = p * Height / 100;
				r.Width = Width;
				g.FillRectangle(_foreBrush, r);
			}
		}


		private int _lwBorderGap=0;

		public int LWBorderGap
		{
			get
			{
				return _lwBorderGap;
			}
			set
			{
				_lwBorderGap = value;
			}
		}



		internal GraphicsPath _lwBorderPath;
		internal GraphicsPath _lwClipPath;
		internal void CreateBorder()
		{
			float bw = (float)_lwBorderWidth;
			float bw2 = (float)_lwBorderWidth / 2;
			float br2 = (float)_lwBorderRadius * 2;
			float br = (float)_lwBorderRadius;
			if (_lwBorderRadius > 0)
			{

				_lwBorderPath = new GraphicsPath();
				_lwBorderPath.AddArc(bw2, bw2, br2, br2, 180, 90);
				_lwBorderPath.AddLine(br + bw2, bw2, Width - br - bw2, bw2);
				_lwBorderPath.AddArc(Width - br2 - bw2, bw2, br2, br2, 270, 90);
				_lwBorderPath.AddLine(Width - bw2, br + bw2, Width - bw2, Height - br - bw2);
				_lwBorderPath.AddArc(Width - br2 - bw2, Height - br2 - bw2, br2, br2, 0, 90);
				_lwBorderPath.AddLine(br + bw2, Height - bw2, Width - br - bw2, Height - bw2);
				_lwBorderPath.AddArc(bw2, Height - br2 - bw2, br2, br2, 90, 90);
				_lwBorderPath.AddLine(bw2, br + bw2, bw2, Height - br - bw2);
				_lwBorderPath.CloseFigure();

			}
			else
			{
				_lwBorderPath = new GraphicsPath();
				RectangleF clipRect = (RectangleF)_lwRectangle;
				clipRect.X += bw;
				clipRect.Y += bw;
				clipRect.Width -= 2 * bw;
				clipRect.Height -= 2 * bw;
				_lwBorderPath.AddRectangle(clipRect);
				_lwBorderPath.CloseFigure();

			}


			float shftW = 0.02f;
			float shftH = 0.02f;
			
			if (_lwBorderGap > 0)
			{
				//shft = 
				shftW  = -  ((float)_lwBorderGap / Width);
				shftH = -  ((float)_lwBorderGap / Height);
				//Console.WriteLine(-(float)_lwBorderGap / Width);
			}

			_lwClipPath = (GraphicsPath)_lwBorderPath.Clone();
			Matrix m = new Matrix();
			m.Translate(bw2 - Width * shftW / 2, bw2 - Height * shftH / 2);
			m.Scale(1 - (float)(bw / Width) + shftW, 1 - (float)(bw / Height) + shftH);
			_lwClipPath.Transform(m);

		}
		internal void DrawBorder(Graphics g)
		{
			Pen _p = new Pen(_lwBorderColor, _lwBorderWidth);
			//_p = new Pen(Color.Red, 1);

			//g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
			if (_lwBorderPath != null)
			{
				g.DrawPath(_p, _lwBorderPath);
				//g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
			}

			return;
			/*
			 if (_lwBorderRadius > 0)
			 {
				 float brp4 = (float)_lwBorderRadius / 4;
				 float br2 = (float)_lwBorderRadius * 2;
				 float br = (float)_lwBorderRadius;


				 Console.WriteLine("XXxxxx");
				 g.DrawArc(_p, bw2 - 1, bw2 - 1, br2, br2, 180, 90);
				 g.DrawArc(_p, Width - br2 - bw2 + 1, bw2 - 1, br2, br2, 270, 90);

				 g.DrawArc(_p, bw2 - 1, Height - br2 - bw2 + 1, br2, br2, 90, 90);
				 g.DrawArc(_p, Width - br2 - bw2 + 1, Height - br2 - bw2 + 1, br2, br2, 0, 90);

				 g.DrawLine(_p, br + bw2 - 1, bw2 - 1, Width - br - bw2 + 1, bw2 - 1);
				 g.DrawLine(_p, br + bw2 - 1, Height - bw2 + 1, Width - br - bw2 + 1, Height - bw2 + 1);

				 g.DrawLine(_p, bw2 - 1, br + bw2 - 1, bw2 - 1, Height - br - bw2 + 1);
				 g.DrawLine(_p, Width - bw2 + 1, br + bw2 - 1, Width - bw2 + 1, Height - br - bw2 + 1);
				
				 GraphicsPath gp = new GraphicsPath();
				 gp.AddArc(brp4 - 1, brp4 - 1, br2, br2, 180, 90);
				 gp.AddLine(br + brp4 - 1, brp4 - 1, Width - br - brp4 + 1, brp4 - 1);
				 gp.AddArc(Width - br2 - brp4 + 1, brp4 - 1, br2, br2, 270, 90);
				 gp.AddLine(Width - brp4 + 1, br + brp4 - 1, Width - brp4 + 1, Height - br - brp4 + 1);
				 gp.AddArc(Width - br2 - brp4 + 1, Height - br2 - brp4 + 1, br2, br2, 0, 90);
				 gp.AddLine(br + brp4 - 1, Height - brp4 + 1, Width - br - brp4 + 1, Height - brp4 + 1);
				 gp.AddArc(brp4 - 1, Height - br2 - brp4 + 1, br2, br2, 90, 90);
				 gp.AddLine(brp4 - 1, br + brp4 - 1, brp4 - 1, Height - br - brp4 + 1);
				 gp.CloseFigure();

				 //Region rg = new Region(_lwBorderPath);
				
				 g.SetClip(gp);

				 g.DrawPath(_p, gp);

			 }
			 else
			 {
			 }	*/

		}

		protected override void WndProc(ref Message m)
		{

			if (DesignMode)
			{
				base.WndProc(ref m);
				return;
			}

			//if (m.Msg == Win32.WM_ERASEBKGND)//optional - needs more testing
			if (m.Msg == Win32.WM_PAINT)
			{
				base.WndProc(ref m);
				if (!DesignMode)
				{

					if (_lwBitmap == null)
					{
						//OnResize(null);
					}

					DisposeInternal();
					CreateBitmap();
					if (_lwClipPath != null)
					{
						_lwGraphics.SetClip(_lwClipPath);
					}
					switch (_lwOrientation)
					{
						case Utils.ProgressBarOrientation.Horizontal:
							DrawHorizontal(_lwGraphics);
							break;
						case Utils.ProgressBarOrientation.Vertical:
							DrawVertical(_lwGraphics);
							break;
					}
					if (_lwBorderWidth > 0)
					{
						_lwGraphics.SetClip(_lwRectangle);
						DrawBorder(_lwGraphics);
					}

					//_lwGraphics.DrawLine(Pens.Red, 0, 0, Parent.Location.X, 10);
					//DrawToBitmap(_lwBitmap, _lwRectangle);
					/*if (_lwTransparency)
					{
						//Utils.BitmapMakeTransparent(ref _lwBitmap, ref _lwRectangle, ref  bc, ref gc, ref  rc);
						//or
						//Utils.BitmapMakeTransparentUnsafe(ref _lwBitmap, ref _lwRectangle, ref  bc, ref gc, ref  rc); //I suspect this one is faster

					}  */
				}



				return;
			}
			base.WndProc(ref m);
		}
	}
}
